package com.vimeworks.vimemannager.ejb.generico;

import java.io.Serializable;
import java.util.List;

import javax.ejb.Stateless;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TransactionRequiredException;

import org.apache.log4j.Logger;

import com.vimeworks.vimemannager.ejb.exeptions.BusquedaException;
import com.vimeworks.vimemannager.ejb.exeptions.EntidadNoEliminadaException;
import com.vimeworks.vimemannager.ejb.exeptions.EntidadNoGuardadaException;
import com.vimeworks.vimemannager.ejb.exeptions.SqlIncorrectoException;

/**
 * Session Bean implementation class GenericBean
 */
@Stateless
public class GenericBean<T, Identificador extends Serializable> implements GenericBeanLocal<T, Identificador> {

	private static final Logger log = Logger.getLogger(GenericBean.class);
	
	private final Class<T> type;
	
	@PersistenceContext(unitName = "vimeManagerPU")
	protected EntityManager em;
	
	/**
	 * Constructor por defecto de la clase
	 * 
	 * @param type la clase de la entidad a utilizar
	 */
    public GenericBean(Class<T> type) {
    	this.type = type;
    }

	/* (non-Javadoc)
	 * @see com.vimeworks.vimemannager.ejb.generico.GenericBeanLocal#guardar(java.lang.Object)
	 */
	public void guardar(T o) throws EntidadNoGuardadaException {
		try {
			em.persist(o);
		} catch (EntityExistsException e) {
			log.error(" --- > La entidad " + o.getClass() + " a guardar ya existe", e);
			throw new EntidadNoGuardadaException(e);
		} catch (IllegalStateException e) {
			log.error(" --- > La entidad " + o.getClass() + " no se ha podido guardar", e);
			throw new EntidadNoGuardadaException(e);
		} catch (IllegalArgumentException e) {
			log.error(" --- > La entidad " + o.getClass() + " no se ha podido guardar", e);
			throw new EntidadNoGuardadaException(e);
		} catch (TransactionRequiredException e) {
			log.error(" --- > La entidad " + o.getClass() + " no se ha podido guardar", e);
			throw new EntidadNoGuardadaException(e);
		}
	}

	/* (non-Javadoc)
	 * @see com.vimeworks.vimemannager.ejb.generico.GenericBeanLocal#guardarOActualizar(java.lang.Object)
	 */
	public T guardarOActualizar(T o) throws EntidadNoGuardadaException {
		try {
			return em.merge(o);
		} catch (IllegalStateException e) {
			log.error(" --- > La entidad " + o.getClass() + " no se ha podido guardar", e);
			throw new EntidadNoGuardadaException(e);
		} catch (IllegalArgumentException e) {
			log.error(" --- > La entidad " + o.getClass() + " no se ha podido guardar", e);
			throw new EntidadNoGuardadaException(e);
		} catch (TransactionRequiredException e) {
			log.error(" --- > La entidad " + o.getClass() + " no se ha podido guardar", e);
			throw new EntidadNoGuardadaException(e);
		}
	}

	/* (non-Javadoc)
	 * @see com.vimeworks.vimemannager.ejb.generico.GenericBeanLocal#eliminar(java.lang.Object)
	 */
	public void eliminar(T o) throws EntidadNoEliminadaException {
		try {
			T entidadEliminar = em.merge(o);
			em.remove(entidadEliminar);
		} catch (IllegalStateException e) {
			log.error(" --- > La entidad " + o.getClass() + " no se ha podido guardar", e);
			throw new EntidadNoEliminadaException(e);
		} catch (IllegalArgumentException e) {
			log.error(" --- > La entidad " + o.getClass() + " no se ha podido guardar", e);
			throw new EntidadNoEliminadaException(e);
		} catch (TransactionRequiredException e) {
			log.error(" --- > La entidad " + o.getClass() + " no se ha podido guardar", e);
			throw new EntidadNoEliminadaException(e);
		}
	}
	
	/* (non-Javadoc)
	 * @see com.vimeworks.vimemannager.ejb.generico.GenericBeanLocal#buscarPorCodigo(java.io.Serializable)
	 */
	public T buscarPorCodigo(Identificador id) throws BusquedaException {
		try {
			T o = (T) em.find(type, id);
			if (o == null) {
				throw new BusquedaException("No existe ".concat(type.getSimpleName()).concat(" con codigo: " + id));
			}
			return o;
		} catch (IllegalStateException e) {
			log.error(" --- > La entidad con id: " + id + " no se ha encontrado", e);
			throw new BusquedaException(e);
		} catch (IllegalArgumentException e) {
			log.error(" --- > La entidad con id: " + id + " no se ha encontrado", e);
			throw new BusquedaException(e);
		}
	}

	/* (non-Javadoc)
	 * @see com.vimeworks.vimemannager.ejb.generico.GenericBeanLocal#obtenerTodos(java.lang.String)
	 */
	@SuppressWarnings("unchecked")
	public List<T> obtenerTodos(String propiedadOrden)
			throws SqlIncorrectoException {
		StringBuffer sql = new StringBuffer();
		sql.append("SELECT o FROM ");
		sql.append(type.getSimpleName());
		sql.append(" o");

		if (propiedadOrden != null) {
			sql.append(" ORDER BY o.");
			sql.append(propiedadOrden);
		}

		Query q = null;
		try {
			q = em.createQuery(sql.toString());
		} catch (IllegalStateException e) {
			throw new SqlIncorrectoException(e);
		} catch (IllegalArgumentException e) {
			throw new SqlIncorrectoException(e);
		}

		return q.getResultList();
	}

}
